/*
 * Copyright (C), 2002-2017, 苏宁易购电子商务有限公司
 * FileName: ActivityServiceImpl.java
 * Author:   15050536
 * Date:     2017年3月24日 下午6:24:30
 * Description: //模块目的、功能描述      
 * History: //修改记录
 * <author>      <time>      <version>    <desc>
 * 修改人姓名             修改时间            版本号                  描述
 */
package com.suning.sawp.member.service.impl;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.suning.nsfuaa.employee.dto.EmployeeInfo;
import com.suning.sawp.constants.CacheKeyConstants;
import com.suning.sawp.constants.ClerkConstants;
import com.suning.sawp.constants.ConfigConstants;
import com.suning.sawp.constants.ErrorCodeConstants;
import com.suning.sawp.dto.common.ReturnMsg;
import com.suning.sawp.dto.esb.CustSocietyInfoStruct;
import com.suning.sawp.dto.esb.LocateMemberInfo;
import com.suning.sawp.dto.esb.QuerySocialityInfoResp;
import com.suning.sawp.dto.mainpush.StoreManDto;
import com.suning.sawp.dto.storeman.Category;
import com.suning.sawp.exception.SawpException;
import com.suning.sawp.intf.dao.IndexCardTaskDaoService;
import com.suning.sawp.intf.esb.MemberInfoService;
import com.suning.sawp.intf.storeman.StoreManService;
import com.suning.sawp.member.constant.MemberConstants;
import com.suning.sawp.member.dao.ActivityDao;
import com.suning.sawp.member.dao.LabelDao;
import com.suning.sawp.member.dao.MemCustomerDao;
import com.suning.sawp.member.dto.Activity;
import com.suning.sawp.member.dto.ActivityStore;
import com.suning.sawp.member.dto.CustomerDetail;
import com.suning.sawp.member.dto.ExpandEmployee;
import com.suning.sawp.member.dto.MemCustomer;
import com.suning.sawp.member.dto.MemCustomerIntentCate;
import com.suning.sawp.member.dto.MemCustomerIntentCmmdty;
import com.suning.sawp.member.dto.MemLabelRel;
import com.suning.sawp.member.dto.StoreCate;
import com.suning.sawp.member.dto.StoreExpand;
import com.suning.sawp.member.service.ActivityService;
import com.suning.sawp.member.vo.ActivityListVo;
import com.suning.sawp.member.vo.ActivityVo;
import com.suning.sawp.member.vo.CustLabelVo;
import com.suning.sawp.member.vo.CustomerVo;
import com.suning.sawp.member.vo.LabelVo;
import com.suning.sawp.member.vo.MemCustomerDetailResponse;
import com.suning.sawp.member.vo.MemCustomerIntentCateVo;
import com.suning.sawp.member.vo.MemCustomerIntentCmmdtyVo;
import com.suning.sawp.member.vo.MemberExtensionStatisVo;
import com.suning.sawp.member.vo.StoreCateVo;
import com.suning.sawp.member.vo.StoreExpandEmployeeVo;
import com.suning.sawp.member.vo.StoreExpandVo;
import com.suning.sawp.po.bi.BIIndexTaskCardEntity;
import com.suning.sawp.po.customer.LastSelEmpBean;
import com.suning.sawp.service.impl.oga.OgaService;
import com.suning.sawp.service.util.AESUtils;
import com.suning.sawp.service.util.DateUtils;
import com.suning.sawp.service.util.RedisCacheUtils;

/**
 * 新会员拓展 活动 service 实现类
 *
 * @author 15050536 石键平
 */
@Service(value = "MemActivityService")
public class ActivityServiceImpl implements ActivityService {

	// 日志对象
	private static final Logger LOGGER = LoggerFactory.getLogger(ActivityServiceImpl.class);

	@Autowired
	private StoreManService storeManService;

	@Autowired
	private MemberInfoService memberInfoService;

	@Autowired
	private OgaService ogaService;

	@Resource
	IndexCardTaskDaoService indexCardTaskDaoService;

	@Autowired
	private ActivityDao activityDao;

	@Autowired
	private MemCustomerDao customerDao;

	@Autowired
	private LabelDao labelDao;

	@Autowired
	private RedisCacheUtils redisClient;

	/**
	 * 店长维度新增活动
	 * 
	 * 根据传入的vo 获得对应的dto 然后数据分别入库
	 *
	 * @param activity
	 */
	@Transactional
	@Override
	public ReturnMsg<Activity> addActivityByShopKeeper(ActivityVo activityVo, String staffId) {
		LOGGER.info("待保存的门店拓展活动vo:{},操作人：{}", activityVo, staffId);
		ReturnMsg<Activity> returnMsg = new ReturnMsg<Activity>();
		StoreManDto storeMan = null;
		try {
			// 根据当前登录人的工号，查询此人相关的一系列信息
			storeMan = storeManService.queryStoreManAttachInfo(staffId);

			// 查询当前门店本月有多少活动了
			Long activityNum = countStoreActivity(storeMan.getStoreCode());
			if (activityNum >= 10) {
				returnMsg.setError(ErrorCodeConstants.ERR_MEM_0050);
				return returnMsg;
			}
			// 新增活动，参数校验
			check(returnMsg, activityVo, storeMan);

		} catch (Exception e) { // 判断各种校验，发生异常，则告诉给前端
			LOGGER.error("新增门店拓展活动数据校验失败", e);
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0001);
			returnMsg.setErrorMessage(String.format("保存失败:%s", e.getMessage()));
		}
		if (ReturnMsg.FAIL.equals(returnMsg.getRetFlag())) {
			return returnMsg;
		}
		try {
			Activity activity = activityVo.getActivity();
			this.fillActivity(activity, storeMan);
			// 保存活动
			activityDao.saveActivity(activity);
			Long activityId = activity.getId();
			if (activityId == null) { // 保存失败
				returnMsg.setError(ErrorCodeConstants.ERR_MEM_0001);
				return returnMsg;
			}
			ActivityStore as = activityVo.getActivityStore(activityId, storeMan.getStoreCode(), storeMan.getStoreName());
			// 保存活动门店对象
			activityDao.saveActivityStore(as);

			// 保存门店品类对象
			List<StoreCate> sc = activityVo.getStoreCates(activityId, storeMan.getStoreCode());
			activityDao.batchSaveStoreCates(sc);
			List<String> ddList = new ArrayList<String>();
			for (StoreCate storeCate : sc) {
				List<EmployeeInfo> empList = storeManService.getClerksInStoreByStoreCodeAndCateCode(storeMan.getStoreCode(), ClerkConstants.SALE_GUIDE, storeCate.getCateCode());
				getDDList(ddList, empList);
			}
			// 督导卡片提醒
			saveToTaskCard(ddList);

			// 删除活动缓存对应的数据
			delActivityKey(storeMan.getStoreCode());
		} catch (Exception e) {
			String errorMsg = "新增门店拓展活动失败";
			LOGGER.error(errorMsg, e);
			// 抛出异常，以便事务回滚
			throw new SawpException(errorMsg, e);
		}
		return returnMsg;
	}

	/**
	 * 先做一系列校验，如果有参数不合规范，返回给前端
	 *
	 * @return
	 */
	private void check(ReturnMsg<Activity> returnMsg, ActivityVo activityVo, StoreManDto storeMan) {
		returnMsg.setRetFlag(ReturnMsg.FAIL);
		returnMsg.setErrorCode(ErrorCodeConstants.ERR_MEM_0004);

		// 判断是否是店长
		if (!checkAuth(storeMan, returnMsg)) {
			return;
		}

		// 活动的基本要素都为空的情况下，不可以创建活动，直接返回空
		if (checkNull(activityVo.getName(), activityVo.getStartTime(), activityVo.getEndTime())) {
			returnMsg.setErrorMessage("门店外拓活动必填参数有为空的情况");
			return;
		}
		if (activityVo.getName().length() > 20) {
			returnMsg.setErrorMessage("活动名称不可以超过20个字");
			return;
		}

		Date startTime = DateTime.parse(activityVo.getStartTime(), MemberConstants.formatter).toDate();
		Date endTime = DateTime.parse(activityVo.getEndTime(), MemberConstants.formatter).toDate();
		// 开始时间不在当前时间之后，这个活动创建的没有意义
		if (!startTime.after(new Date())) {
			returnMsg.setErrorMessage("开始考核时间必须大于今天");
			return;
		}

		if (endTime.before(startTime)) {
			returnMsg.setErrorMessage("结束时间不可以小于开始时间");
			return;
		}

		// 店长维度-门店是固定的,(检查目标金额格式)
		String storeTargetAmount = activityVo.getTargetAmount();
		if (checkNull(storeTargetAmount) || !checkNumber(storeTargetAmount)) {
			returnMsg.setErrorMessage(String.format("新增门店外拓活动时,门店:%s 对应的目标金额:%s,异常", storeMan.getStoreName(), storeTargetAmount));
			return;
		}

		if (CollectionUtils.isEmpty(activityVo.getCates())) {
			returnMsg.setErrorMessage("新增/编辑门店外拓活动时，未选择门店关联的品类");
			return;
		}
		for (StoreCateVo cate : activityVo.getCates()) {
			String targetAmount = cate.getTargetAmount();
			// 店长维度-门店是固定的,(检查目标金额格式)
			if (checkNull(targetAmount) || !checkNumber(targetAmount)) {
				returnMsg.setErrorMessage(String.format("新增/编辑门店外拓活动时,[%s]对应的目标金额:%s,异常", cate.getCateName(), targetAmount));
				return;
			}
		}

		// 验证之后没问题，则重置为成功
		returnMsg.setRetFlag(ReturnMsg.SUCCESS);
		returnMsg.setErrorCode(StringUtils.EMPTY);
	}

	/**
	 * 
	 * 校验，只有店长才可创建活动
	 *
	 * @param storeMan
	 * @param returnMsg
	 * @return
	 */
	private boolean checkAuth(StoreManDto storeMan, ReturnMsg<Activity> returnMsg) {
		// 登录人员不存在
		if (storeMan == null) {
			LOGGER.warn("保存门店外拓活动：操作人员为空");
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0002);
			return false;
		}
		if (!ClerkConstants.STORE_KEEPER.equals(storeMan.getPositionId())) {
			LOGGER.warn("只有店长才可创建活动，当前操作人：{}({})，非店长角色.", storeMan.getStaffName(), storeMan.getStaffId());
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0003);
			return false;
		}
		return true;
	}

	/**
	 * 
	 * 给活动bean赋一些非页面提交的值
	 *
	 * @param activity
	 * @param storeMan
	 */
	private void fillActivity(Activity activity, StoreManDto storeMan) {
		activity.setAreaCode(storeMan.getSaleRegionCode());
		activity.setCreateTime(new Date());
		activity.setCreateUser(storeMan.getStaffId());
		activity.setCreateUserName(storeMan.getStaffName());
		activity.setCreatorRole(MemberConstants.TWO); // 2 表示店长
		activity.setFlow(MemberConstants.ONE); // 0 表示刚创建,1表示店长已分配过品类目标
	}

	/**
	 * 
	 * 判断是否有空的字符串
	 * 
	 * @param args
	 * @return
	 */
	private boolean checkNull(String... args) {
		for (String arg : args) {
			if (StringUtils.isEmpty(arg)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 判断是否是合法的金额数据
	 *
	 * @param number
	 * @return
	 */
	private boolean checkNumber(String number) {
		String rex = "^[1-9]\\d*(\\.\\d+)?$";
		Pattern p = Pattern.compile(rex);
		Matcher m = p.matcher(number);
		return m.find();
	}

	@Override
	public ReturnMsg<JSONObject> findActivityVoById(Long activityId, String staffId) {
		ReturnMsg<JSONObject> returnMsg = new ReturnMsg<JSONObject>();
		// 此方法不加缓存了，查询这个对象的目的就是为了修改
		try {
			StoreManDto storeMan = storeManService.queryStoreManAttachInfo(staffId);
			String storeCode = storeMan.getStoreCode();

			// 查询活动基础信息
			Activity activity = activityDao.selectActivityInfoById(String.valueOf(activityId));
			// 查询活动关联的门店信息
			ActivityStore activityStore = activityDao.findActivityStoreByActivityIdAndStoreCode(activityId, storeCode);
			// 查询当前门店关联的品类目标信息
			List<StoreCate> storeCates = activityDao.queryStoreCatesByActivityIdAndStoreCode(activityId, storeCode);

			ActivityVo activityVo = new ActivityVo();
			activityVo.setId(String.valueOf(activity.getId()));
			activityVo.setName(activity.getName());
			activityVo.setStartTime(new DateTime(activity.getStartTime()).toString(MemberConstants.formatter));
			activityVo.setEndTime(new DateTime(activity.getEndTime()).toString(MemberConstants.formatter));

			activityVo.setCreateUser(activity.getCreateUser());
			activityVo.setCreatorRole(String.valueOf(activity.getCreatorRole()));
			if (activityStore != null) {
				if (activityStore.getTargetAmount() != null) {
					activityVo.setTargetAmount(activityStore.getTargetAmount().toString());
				}
				activityVo.setStoreCode(activityStore.getStoreCode());
				activityVo.setActivityStoreId(String.valueOf(activityStore.getId()));
			}

			List<StoreCateVo> cates = Lists.newArrayList();

			for (StoreCate sc : storeCates) {
				StoreCateVo cateVo = new StoreCateVo();
				cateVo.setStoreCateId(String.valueOf(sc.getId()));
				cateVo.setCateCode(sc.getCateCode());
				cateVo.setCateName(sc.getCateName());
				cateVo.setTargetAmount(sc.getTargetAmount().toString());
				cates.add(cateVo);
			}
			activityVo.setCates(cates);

			JsonConfig config = new JsonConfig();
			config.setExcludes(new String[] { "activity", "stores" });
			JSONObject json = new JSONObject();
			json.put("activity", JSONObject.fromObject(activityVo, config));
			returnMsg.setData(json);
		} catch (Exception e) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0005);
			LOGGER.error("查询活动vo发生异常", e);
		}
		return returnMsg;

	}

	/**
	 * 
	 * 修改活动
	 *
	 * @param activityVo
	 *            前端传来的vo对象
	 * @param staffId
	 */
	@Transactional
	@Override
	public ReturnMsg<Activity> modifyActivity(ActivityVo activityVo, String staffId) {
		ReturnMsg<Activity> returnMsg = new ReturnMsg<Activity>();
		String activityIdStr = activityVo.getId();
		Long activityId = Long.parseLong(activityIdStr);
		if (checkNull(activityIdStr)) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0006);
			return returnMsg;
		}
		Activity activityFromPage = activityVo.getActivity();
		Activity activityFromDB = activityDao.selectActivityInfoById(activityIdStr);

		modifyActivityCheck(returnMsg, activityVo, activityFromDB, staffId);
		if (ReturnMsg.FAIL.equals(returnMsg.getRetFlag())) { // 校验不通过，则返回错误信息到客户端
			return returnMsg;
		}
		activityFromPage.setId(activityId);
		activityFromPage.setUpdateUser(staffId);
		activityFromPage.setUpdateTime(new Date());
		if (MemberConstants.ZERO.equals(activityFromDB.getFlow())) {
			activityFromPage.setFlow(MemberConstants.ONE);
		}
		StoreManDto storeMan = null;
		try {
			storeMan = storeManService.queryStoreManAttachInfo(staffId);
			// 更新activity
			activityDao.updateActivity(activityFromPage);
			// 更新门店目标金额
			activityDao.updateActivityStore(activityVo.getActivityStore(activityId, storeMan.getStoreCode(), storeMan.getStoreName()));
			// 品类目标vo列表
			List<StoreCateVo> scList = activityVo.getCates();

			List<Long> scIds = new ArrayList<Long>();
			List<String> ddList = new ArrayList<String>();
			for (StoreCateVo scVo : scList) { // 可能有新增，可能有编辑，所以不做批处理
				if (StringUtils.isNotEmpty(scVo.getStoreCateId())) { // 传了id的，表示更新
					Long scId = Long.parseLong(scVo.getStoreCateId());
					StoreCate sc = new StoreCate(scId, new BigDecimal(scVo.getTargetAmount()));
					activityDao.updateStoreCates(sc);
					scIds.add(scId);
				} else { // 没传的，表示新增
					String cateCode = scVo.getCateCode();
					String cateName = ConfigConstants.DEFAULT_CATE_MAP.get(cateCode);
					StoreCate sc = new StoreCate(activityId, storeMan.getStoreCode(), cateCode, cateName, new BigDecimal(scVo.getTargetAmount()));
					activityDao.saveStoreCates(sc);
				}
				List<EmployeeInfo> empList = storeManService.getClerksInStoreByStoreCodeAndCateCode(storeMan.getStoreCode(), ClerkConstants.SALE_GUIDE, scVo.getCateCode());
				getDDList(ddList, empList);
			}
			// 库里已有的数据
			List<StoreCate> storeCatesInDB = activityDao.queryStoreCatesByActivityIdAndStoreCode(activityId, storeMan.getStoreCode());
			// 原来库里有数据，修改的时候，可能只提交了部分，则剩下的老数据得删除掉
			if (CollectionUtils.isNotEmpty(storeCatesInDB)) {
				delOtherCate(storeCatesInDB, scIds);
			}

			// 督导卡片提醒
			saveToTaskCard(ddList);

			delActivityKey(storeMan.getStoreCode());
		} catch (Exception e) {
			String errorMsg = "修改门店拓展活动失败";
			LOGGER.error(errorMsg, e);
			// 抛出异常，以便事务回滚
			throw new SawpException(errorMsg, e);
		}

		return returnMsg;
	}

	/**
	 * 删除一些门店关联的品类
	 *
	 * @param storeCatesInDB
	 * @param scIds
	 */
	private void delOtherCate(List<StoreCate> storeCatesInDB, List<Long> scIds) {
		for (StoreCate sc : storeCatesInDB) {
			// 客户端传过来的品类集合，不含此品类的话，则需要删除
			if (!scIds.contains(sc.getId())) {
				activityDao.deleteStoreCateById(sc.getId());
			}
		}
	}

	private void getDDList(List<String> ddList, List<EmployeeInfo> empList) {
		if (CollectionUtils.isEmpty(empList)) {
			return;
		}
		for (EmployeeInfo emp : empList) {
			ddList.add(emp.getEmployeeId());
		}
	}

	/**
	 * 
	 * 修改活动的时候，做的一些校验
	 * 
	 * @param returnMsg
	 * @param activityVo
	 * @param activityFromDB
	 * @param staffId
	 */
	private void modifyActivityCheck(ReturnMsg<Activity> returnMsg, ActivityVo activityVo, Activity activityFromDB, String staffId) {

		Date today = new Date();
		Date startTimeDB = activityFromDB.getStartTime();
		Date endTimeDB = activityFromDB.getEndTime();
		// 考核活动结束了,不可以修改
		if (endTimeDB.before(today)) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0007);
			return;
		}
		// 活动开始后，不可以修改开始时间
		if (startTimeDB.before(today) && startTimeDB.compareTo(activityVo.getActivity().getStartTime()) != 0) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0008);
			return;
		}
		// 目标金额格式不正确
		if (checkNull(activityVo.getTargetAmount()) || !checkNumber(activityVo.getTargetAmount())) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0010);
			return;
		}

		if (CollectionUtils.isEmpty(activityVo.getCates())) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0011);
			return;
		}
		for (StoreCateVo cate : activityVo.getCates()) {
			String targetAmount = cate.getTargetAmount();
			// 店长维度-门店是固定的,(检查目标金额格式)
			if (checkNull(targetAmount) || !checkNumber(targetAmount)) {
				returnMsg.setError(ErrorCodeConstants.ERR_MEM_0010);
				returnMsg.setErrorMessage(String.format("编辑门店外拓活动时,[%s]对应的目标金额:%s,异常", cate.getCateName(), targetAmount));
				return;
			}
		}
	}

	@Override
	public ReturnMsg<JSONObject> queryActivityList(String status, String cateCode, int startIndex, String staffId) {
		LOGGER.info("查询门店外拓活动列表，参数为:status={},cateCode={},startIndex={},staffId={}", status, cateCode, startIndex, staffId);
		ReturnMsg<JSONObject> returnMsg = new ReturnMsg<JSONObject>();

		try {
			StoreManDto storeMan = storeManService.queryStoreManAttachInfo(staffId);
			String positionId = storeMan.getPositionId();
			// 活动列表缓存
			String key = String.format(CacheKeyConstants.MemberExpand.ACTIVITY_LIST, storeMan.getStoreCode(), status);
			String field = positionId + "_" + cateCode + "_" + startIndex;
			if (ClerkConstants.SALE_GUIDE.equals(positionId)) {
				field += "_" + staffId;// 如果是督导维度，可能对于的品类不一样，所以需要加上staffId
			}
			Type type = new TypeToken<ReturnMsg<JSONObject>>() {
			}.getType();
			ReturnMsg<JSONObject> result = redisClient.hget(key, field, type);
			if (result != null) {
				return result;
			}

			if (ClerkConstants.STORE_KEEPER.equals(positionId)) {
				queryActivityListByDZ(returnMsg, status, startIndex, storeMan);
			} else if (ClerkConstants.SALE_GUIDE.equals(positionId)) {
				queryActivityListByDD(returnMsg, status, cateCode, startIndex, storeMan);
			} else if (ClerkConstants.SALES_CLERK.equals(positionId) || ClerkConstants.SALES_PROMOTION.equals(positionId)) {
				queryActivityListByDY(returnMsg, status, startIndex, staffId);
			} else {
				LOGGER.warn("未知的岗位：{},试图查询外拓活动列表，被拒绝", positionId);
				returnMsg.setError(ErrorCodeConstants.ERR_MEM_0012);
				return returnMsg;// 暂无权限查询
			}
			// 保存到缓存
			redisClient.hsetWithMyExpireTime(key, field, returnMsg, CacheKeyConstants.MemberExpand.HOUR_EXPIRE_TIME);
		} catch (Exception e) {
			LOGGER.error("查询门店外拓活动列表失败", e);
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0013);
			String errorMsg = returnMsg.getErrorMessage() + e.getMessage();
			returnMsg.setErrorMessage(errorMsg);
		}
		return returnMsg;
	}

	/**
	 * 店长维度查询活动列表
	 *
	 */
	private void queryActivityListByDZ(ReturnMsg<JSONObject> returnMsg, String status, int startIndex, StoreManDto storeMan) {
		LOGGER.info("店长维度查询活动列表");
		// 查询本门店所有进行中的活动 ,即考核还未开始的活动 start_time > now()
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("status", status);
		params.put("storeCode", storeMan.getStoreCode());
		params.put("startIndex", startIndex);
		params.put("pageSize", MemberConstants.PAGE_SIZE);

		JSONObject json = new JSONObject();
		Long total = activityDao.countActivityList4DZ(params);
		if (total > 0) { // 有数据，再去拉详情
			List<ActivityListVo> list = activityDao.queryActivityList4DZ(params);
			json.put("activities", list);
		} else {
			json.put("activities", new ArrayList<ActivityListVo>());
		}
		json.put("total", total);
		returnMsg.setData(json);
	}

	/**
	 * 督导维度查询活动列表
	 *
	 */
	private void queryActivityListByDD(ReturnMsg<JSONObject> returnMsg, String status, String cateCode, int startIndex, StoreManDto storeMan) {
		LOGGER.info("督导维度查询活动列表");
		String currentCateCode = cateCode;
		// 查询督导关联的品类列表
		List<Category> categories = storeMan.getCategories();
		// 按品类顺序获取活动列表，直到可以查询到对应的活动列表，否则继续下个类别；如果所有的类别都没有数据，则返回空
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("status", status);
		params.put("storeCode", storeMan.getStoreCode());

		params.put("startIndex", startIndex);
		params.put("pageSize", MemberConstants.PAGE_SIZE);

		JSONObject json = new JSONObject();

		if (CollectionUtils.isEmpty(categories)) {
			LOGGER.warn("督导：{},对应的品类列表为空", storeMan.getStaffName());
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0014);
			return;
		}
		Long total = 0L;
		List<ActivityListVo> list = null;

		// 传了品类，则只查此品类下数据
		if (StringUtils.isNotEmpty(currentCateCode)) {
			params.put("cateCode", currentCateCode);
			total = activityDao.countActivityList4DD(params);
			if (total > 0) { // 查到数据了，那么就结束了
				list = activityDao.queryActivityList4DD(params);
			} else {
				list = new ArrayList<ActivityListVo>();
			}
		} else { // 未传品类，循环迭代获取品类，知道获取到值，或者循环结束
			for (Category category : categories) {
				currentCateCode = category.getCategoryCode();
				params.put("cateCode", currentCateCode);
				total = activityDao.countActivityList4DD(params);
				if (total > 0) { // 查到数据了，那么就跳出循环
					list = activityDao.queryActivityList4DD(params);
					break;
				}
			}
			// 没查到结果了,并且未传品类,取第一个品类
			if (total == 0) { // 没查询到的数据的时候，返回空对象，默认选中第一个品类
				list = new ArrayList<ActivityListVo>();
				currentCateCode = categories.get(0).getCategoryCode();
			}
		}

		List<Map<String, String>> cates = generateCategorys(categories, currentCateCode);
		json.put("activities", list);
		json.put("cates", cates);
		json.put("total", total);
		returnMsg.setData(json);

	}

	// 生成类别数据，返回给前端
	private List<Map<String, String>> generateCategorys(List<Category> categories, String cateCode) {
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		for (int i = 0; i < categories.size(); i++) {
			Map<String, String> map = new HashMap<String, String>(3);
			String cCode = categories.get(i).getCategoryCode();
			map.put("cateCode", cCode);
			map.put("cateName", categories.get(i).getCategoryName());
			map.put("checked", cateCode.equals(cCode) ? "1" : "0"); // 设置默认选中值
			list.add(map);
		}
		return list;
	}

	/**
	 * 店员维度查询活动列表
	 *
	 */
	private void queryActivityListByDY(ReturnMsg<JSONObject> returnMsg, String status, int startIndex, String staffId) {
		LOGGER.info("店员维度查询活动列表");
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("status", status);
		params.put("employeeId", staffId);
		params.put("startIndex", startIndex);
		params.put("pageSize", MemberConstants.PAGE_SIZE);
		JSONObject json = new JSONObject();
		Long total = activityDao.countActivityList4DY(params);
		if (total > 0) {
			List<ActivityListVo> list = activityDao.queryActivityList4DY(params);
			json.put("activities", list);
		} else {
			json.put("activities", new ArrayList<ActivityListVo>());
		}
		json.put("total", total);
		returnMsg.setData(json);
	}

	/**
	 * 查询某活动，某品类下的 地点列表数据
	 * 
	 * @param activityId
	 *            活动id,必传
	 * @param cateCode
	 *            品类编码，必传
	 * @param startIndex
	 *            分页起始位，默认0，非必填
	 * @param storeCateId
	 *            门店品类id,当startIndex > 0 必传，由startIndex=0时，服务器回传给客户端的
	 * @param staffId
	 *            员工工号
	 */
	@Override
	public ReturnMsg<JSONObject> findActivityExpandStatictisByCate(Long activityId, String cateCode, int startIndex, Long scId, String staffId) {
		LOGGER.info("查询活动的统计信息,按地点维度分组[activityService.findActivityExpandStatictisByCate],参数为：activityId={},cateCode={},startIndex={},staffId={}", activityId, cateCode, startIndex, staffId);
		ReturnMsg<JSONObject> returnMsg = new ReturnMsg<JSONObject>();

		// 活动id和品类是必传的
		if (activityId == null || StringUtils.isEmpty(cateCode)) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0031);
			return returnMsg;
		}

		JSONObject json = new JSONObject();
		try {
			Long storeCateId = scId;
			Map<String, Object> params = new HashMap<String, Object>();
			if (storeCateId == null || startIndex == 0) { // 首次，未传此参数，则入库查总统计信息
				StoreManDto storeMan = storeManService.queryStoreManAttachInfo(staffId);

				params.put("activityId", activityId);
				params.put("storeCode", storeMan.getStoreCode());
				params.put("cateCode", cateCode);
				// 查询总的统计信息
				ActivityListVo activityListVo = activityDao.findActivityStatisticByCate(params);
				// activityListVo中有属性 storeCateId
				json.put("activity", activityListVo);

				if (activityListVo != null && StringUtils.isNotEmpty(activityListVo.getStoreCateId())) {
					storeCateId = Long.parseLong(activityListVo.getStoreCateId());
				}
			}
			// 非首次来，或者通过上述代码，查询到了storeCodeId
			if (storeCateId != null) {
				params.clear();
				params.put("storeCateId", storeCateId);
				params.put("startIndex", startIndex);
				params.put("pageSize", MemberConstants.PAGE_SIZE);

				// 查询地点总数
				Long total = activityDao.countExpandStatistic4Activity(params);
				if (total > 0L) {
					// 查询各地址的统计信息
					List<StoreExpandVo> expandList = activityDao.queryExpandStatistic4Activity(params);
					json.put("expandList", expandList);
				} else {
					json.put("expandList", new ArrayList<StoreExpandVo>(0));
				}
				json.put("total", total);
			} else { // 出现此种情况较少
				json.put("total", 0);
				json.put("expandList", new ArrayList<StoreExpandVo>(0));
			}
			returnMsg.setData(json);
		} catch (Exception e) {
			LOGGER.error("查询门店外拓活动地址列表失败，活动id:{},员工：{}，品类：{}", activityId, staffId, cateCode, e);
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0030);
			String errorMsg = returnMsg.getErrorMessage() + e.getMessage();
			returnMsg.setErrorMessage(errorMsg);
		}
		return returnMsg;
	}

	@Override
	public ReturnMsg<JSONObject> findExpandDetailInfo(Long expandId) {
		LOGGER.info("查询外拓活动拓展详情信息，拓展id:{}", expandId);
		ReturnMsg<JSONObject> returnMsg = new ReturnMsg<JSONObject>();
		JSONObject json = new JSONObject();
		if (expandId == null) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0032);
			return returnMsg;
		}
		try {
			StoreExpandVo storeExpandVo = activityDao.findExpandById(expandId);
			List<StoreExpandEmployeeVo> employeeList = activityDao.queryEmployeesByExpandId(expandId);
			storeExpandVo.setEmployeeList(employeeList);
			json.put("expand", storeExpandVo);
			returnMsg.setData(json);
		} catch (Exception e) {
			LOGGER.error("查询外拓详情失败，expandId:{}", expandId, e);
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0033);
			String errorMsg = returnMsg.getErrorMessage() + e.getMessage();
			returnMsg.setErrorMessage(errorMsg);
		}
		return returnMsg;
	}

	/**
	 * 
	 * 保存门店外拓任务 -- 含店员目标数据
	 *
	 * @param storeExpandVo
	 */
	@Transactional
	@Override
	public ReturnMsg<StoreExpand> saveStoreExpand(StoreExpandVo storeExpandVo, String staffId) {
		LOGGER.info("待保存的拓展任务vo:{},操作人：{}", storeExpandVo, staffId);
		ReturnMsg<StoreExpand> returnMsg = new ReturnMsg<StoreExpand>();
		StoreManDto storeMan = null;
		StoreExpand storeExpand = null;
		try {
			// 根据当前登录人的工号，查询此人相关的一系列信息
			storeMan = storeManService.queryStoreManAttachInfo(staffId);
			storeExpand = changeStoreExpandVoToBean(returnMsg, storeExpandVo, storeMan);
		} catch (Exception e) { // 判断各种校验，发生异常，则告诉给前端
			LOGGER.error("新增拓展任务数据校验失败", e);
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0036);
			String errorMsg = String.format(returnMsg.getErrorMessage(), e.getMessage());
			returnMsg.setErrorMessage(errorMsg);
			return returnMsg;
		}
		// 校验没通过，返回空对象
		if (storeExpand == null) {
			return returnMsg;
		}

		if (storeExpand.getId() == null) { // 新增
			activityDao.saveStoreExpand(storeExpand);
			// 更新活动流程
			Activity activity = new Activity();
			activity.setId(storeExpand.getActivityId());
			activity.setFlow(MemberConstants.TWO);
			activityDao.updateActivity(activity);
		} else { // 更新
			activityDao.updateStoreExpand(storeExpand);
		}
		List<ExpandEmployee> list = generateExpandEmployees(storeExpand, storeExpandVo);
		if (CollectionUtils.isEmpty(list)) { // 无店员记录
			return returnMsg;
		}
		// 店员卡片
		List<StoreExpandEmployeeVo> oldEmployees = activityDao.queryEmployeesByExpandId(storeExpand.getId());
		// 批量入库之前，先删除老的数据
		activityDao.deleteEmployeeByExpandId(storeExpand.getId());
		activityDao.batchSaveExpandEmployee(list);

		// 查询需要通知的店员信息
		List<String> employees = getDiffEmployee(list, oldEmployees);
		// 店员卡片任务保存
		saveToTaskCard(employees);

		// 添加到最近选择的店员
		saveLastChooseEmployee(list, staffId);

		// 删除缓存--店员维度的活动列表有可能变化
		delActivityKey(storeExpand.getStoreCode());
		return returnMsg;
	}

	/**
	 * 
	 * 待入库的店员与已存在库中的店员 找区别
	 *
	 * @param needSaveEmployees
	 * @param oldEmployees
	 * @return
	 */
	private List<String> getDiffEmployee(List<ExpandEmployee> needSaveEmployees, List<StoreExpandEmployeeVo> oldEmployees) {
		// list为空的时候，返回空对象
		if (CollectionUtils.isEmpty(needSaveEmployees)) {
			return new ArrayList<String>(0);
		}
		List<String> result = new ArrayList<String>();
		if (CollectionUtils.isEmpty(oldEmployees)) {
			for (ExpandEmployee saveEployee : needSaveEmployees) {
				result.add(saveEployee.getEmployeeId());
			}
			return result;
		}

		// id相同，但是改过目标数量的人，需要重新通知
		for (ExpandEmployee saveEployee : needSaveEmployees) {
			for (StoreExpandEmployeeVo oldEmployee : oldEmployees) {
				// 同一个人，并且目标人数变了，则挑选出来
				if (saveEployee.getEmployeeId().equals(oldEmployee.getEmployeeId()) && !saveEployee.getTargetPeople().equals(oldEmployee.getTargetPeople())) {
					result.add(saveEployee.getEmployeeId());
				}
			}
		}
		// 新增的店员，也需要通知
		for (ExpandEmployee saveEployee : needSaveEmployees) {
			if (!result.contains(saveEployee.getEmployeeId())) {
				result.add(saveEployee.getEmployeeId());
			}
		}

		return result;
	}

	/**
	 * 门店外拓的卡片任务提醒
	 * 
	 * @param employees
	 *            //待提醒的员工
	 */
	private void saveToTaskCard(List<String> employees) {
		if (CollectionUtils.isEmpty(employees)) {
			return;
		}
		Date startTime = new Date();
		long oneDayMillis = 24 * 3600 * 1000;
		Date endTime = new Date(startTime.getTime() + oneDayMillis);
		for (String employeeId : employees) {
			// 设置首页卡片展示
			BIIndexTaskCardEntity entity = new BIIndexTaskCardEntity();
			// 门店月度销售
			entity.setBizKey(BIIndexTaskCardEntity.BizKey.STORE_EXPAND);
			// 卡片类型
			entity.setCardType(BIIndexTaskCardEntity.CardType.CARD_002);
			// 任务卡片分配的人员
			entity.setStaffId(employeeId);
			// 任务卡片开始时间 用当前时间
			entity.setStartTime(startTime);
			// 任务结束结束时间 开始时间往后推三天
			entity.setEndTime(endTime);
			// 卡片提示
			entity.setTaskTips(BIIndexTaskCardEntity.Content.STORE_EXPAND_CONTENT);
			// 卡片标题
			entity.setTitle(BIIndexTaskCardEntity.Title.STORE_EXPAND);
			indexCardTaskDaoService.upsertIndexTaskCard(entity);
		}
	}

	/**
	 * vo转对应的bean
	 */
	private StoreExpand changeStoreExpandVoToBean(ReturnMsg<StoreExpand> returnMsg, StoreExpandVo storeExpandVo, StoreManDto storeMan) {
		String expandId = storeExpandVo.getExpandId();
		String targetPeople = storeExpandVo.getTargetPeople();
		String startTime = storeExpandVo.getStartTime();
		String endTime = storeExpandVo.getEndTime();
		String storeCateIdStr = storeExpandVo.getStoreCateId();
		String place = storeExpandVo.getPlace();
		// 非空校验
		if (checkNull(targetPeople, startTime, endTime, storeCateIdStr, place)) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0034);
			return null;
		}

		Date start = DateTime.parse(startTime, MemberConstants.formatter).toDate();
		Date end = DateTime.parse(endTime, MemberConstants.formatter).toDate();
		// 结束时间不能小于开始时间
		if (end.before(start)) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0035);
			return null;
		}

		Long storeCateId = Long.parseLong(storeCateIdStr);
		StoreCate sc = activityDao.findStoreCateById(storeCateId);
		if (sc == null) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0036);
			String errorMsg = "storeCateId对应的门店品类对象为空：" + storeCateId;
			returnMsg.setErrorMessage(errorMsg);
			return null;
		}
		Activity activity = activityDao.selectActivityInfoById(String.valueOf(sc.getActivityId()));
		Date activityStartTime = activity.getStartTime();
		// 任务结束时间不在活动开始时间之前，报错
		if (!end.before(activityStartTime)) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0035);
			returnMsg.setErrorMessage("任务的结束时间，必须在活动考核的开始时间之前");
			return null;
		}

		// 新增的时候判断已经添加了多少任务了。如果超过100则不允许再建了
		StoreExpand se = new StoreExpand();
		if (StringUtils.isNotEmpty(expandId)) {
			se.setId(Long.parseLong(expandId));
		} else {// 新增
			Long count = activityDao.countExpandByActivityIdAndStoreCode(sc.getActivityId(), sc.getStoreCode());
			if (count.longValue() >= 100) {
				returnMsg.setError(ErrorCodeConstants.ERR_MEM_0049);
				return null;
			}
		}

		se.setActivityId(sc.getActivityId());
		se.setCateCode(sc.getCateCode());
		se.setCateName(sc.getCateName());
		se.setCreateTime(new Date());
		se.setCreateUser(storeMan.getStaffId());
		se.setCreateUserName(storeMan.getStaffName());
		se.setEndTime(end);
		se.setStartTime(start);
		se.setPlace(place);
		se.setStatus(MemberConstants.ONE);
		se.setStoreCateId(storeCateId);
		se.setStoreCode(sc.getStoreCode());
		se.setStoreName(storeMan.getStoreName());
		se.setTargetPeople(Integer.parseInt(targetPeople));

		return se;
	}

	/**
	 * 生成拓展店员列表
	 *
	 * @param se
	 * @param storeExpandVo
	 */
	private List<ExpandEmployee> generateExpandEmployees(StoreExpand se, StoreExpandVo storeExpandVo) {
		// 获取分配的店员信息
		List<StoreExpandEmployeeVo> list = storeExpandVo.getEmployeeList();
		if (CollectionUtils.isEmpty(list)) {
			return null;
		}
		List<ExpandEmployee> employeeList = new ArrayList<ExpandEmployee>(list.size());
		for (StoreExpandEmployeeVo seVo : list) {
			ExpandEmployee expandEmployee = new ExpandEmployee();
			String employeeId = seVo.getEmployeeId();
			String employeeName = seVo.getEmployeeName();
			String targetPeople = seVo.getTargetPeople();
			if (checkNull(employeeId, targetPeople)) {
				continue;
			}
			expandEmployee.setEmployeeId(employeeId);
			expandEmployee.setEmployeeName(employeeName);
			expandEmployee.setTargetPeople(targetPeople);
			expandEmployee.setExpandId(se.getId());
			expandEmployee.setActivityId(se.getActivityId());
			expandEmployee.setCateCode(se.getCateCode());
			expandEmployee.setStoreCode(se.getStoreCode());
			employeeList.add(expandEmployee);
		}
		return employeeList;
	}

	/**
	 * 
	 * 保存下最近选择的店员
	 *
	 * @param list
	 *            待保存的店员列表
	 * @param staffId
	 *            督导工号
	 */
	private void saveLastChooseEmployee(List<ExpandEmployee> list, String staffId) {
		if (CollectionUtils.isEmpty(list)) {
			return;
		}
		List<LastSelEmpBean> lastSelList = new ArrayList<LastSelEmpBean>();
		for (ExpandEmployee expandEmployee : list) {
			LastSelEmpBean lse = new LastSelEmpBean();
			lse.setStaffCode(expandEmployee.getEmployeeId());
			lse.setStaffName(expandEmployee.getEmployeeName());
			lse.setRelCode(staffId);
			lastSelList.add(lse);
		}
		// 保存最近选择的50人
		ogaService.maintainLastSelEmp(lastSelList, staffId);
	}

	@Transactional
	@Override
	public ReturnMsg<Activity> deleteActivity(Long activityId, String staffId, boolean isClient) {
		LOGGER.info("删除活动中，活动id:{},删除人:{}", activityId, staffId);

		ReturnMsg<Activity> returnMsg = new ReturnMsg<Activity>();
		if (activityId == null) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0037);
			return returnMsg;
		}
		try {

			Activity activity = activityDao.selectActivityInfoById(String.valueOf(activityId));
			// 如果是客户端，并且删除人不是创建人，那么问题来了，是没有权限删除的
			if (isClient && !staffId.equals(activity.getCreateUser())) {
				returnMsg.setError(ErrorCodeConstants.ERR_MEM_0038);
				return returnMsg;
			}
			// 查询活动是否已经有拓展用户了
			Long num = activityDao.countCustomerByActivityId(activityId);
			if (num > 0) {
				returnMsg.setError(ErrorCodeConstants.ERR_MEM_0039);
				return returnMsg;
			}
			// 删除
			activityDao.deleteActivityById(activityId);
			String storeCode = "*"; // 大区或分公司删除的时候，缓存全清。。否则只清具体某一门店的数据
			if (isClient) {// 店长删除权限
				StoreManDto storeMan = storeManService.queryStoreManAttachInfo(staffId);
				storeCode = storeMan.getStoreCode();
			}
			// 删除缓存
			delActivityKey(storeCode);
		} catch (Exception e) {
			LOGGER.error("删除活动异常", e);
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0036);
			String errorMsg = String.format(returnMsg.getErrorMessage(), e.getMessage());
			returnMsg.setErrorMessage(errorMsg);
		}
		return returnMsg;
	}

	@Transactional
	@Override
	public ReturnMsg<StoreExpand> deleteStoreExpand(Long expandId, String staffId) {
		LOGGER.info("删除任务中，任务id:{},删除人:{}", expandId, staffId);
		ReturnMsg<StoreExpand> returnMsg = new ReturnMsg<StoreExpand>();
		if (expandId == null) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0040);
			return returnMsg;
		}
		// 查询任务是否有拓展的客户了
		Long num = activityDao.countCustomerByExpandId(expandId);
		if (num > 0) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0041);
			return returnMsg;
		}
		// 删除
		activityDao.deleteExpandById(expandId);
		return returnMsg;
	}

	/**
	 * 
	 * 询价未购的时候，需要查询当前门店正在进行的所有活动列表
	 *
	 * @param staffId
	 * @return
	 */
	@Override
	public ReturnMsg<JSONObject> queryActiveActivities(String staffId) {
		try {
			StoreManDto storeMan = storeManService.queryStoreManAttachInfo(staffId);
			String key = String.format(CacheKeyConstants.MemberExpand.ACTIVITY_ACTIVE_LIST, storeMan.getStoreCode());
			Type type = new TypeToken<ReturnMsg<JSONObject>>() {
			}.getType();
			ReturnMsg<JSONObject> returnMsg = redisClient.get(key, type);
			if (returnMsg != null) { // 缓存有值
				return returnMsg;
			}
			returnMsg = new ReturnMsg<JSONObject>();
			List<ActivityListVo> activities = activityDao.queryActiveActivities(storeMan.getStoreCode(), String.valueOf(MemberConstants.ZERO));
			JSONObject json = new JSONObject();
			json.put("activties", new GsonBuilder().create().toJson(activities));
			returnMsg.setData(json);

			redisClient.setex(key, CacheKeyConstants.MemberExpand.HOUR_EXPIRE_TIME, returnMsg);
			return returnMsg;
		} catch (Exception e) {
			ReturnMsg<JSONObject> returnMsg = new ReturnMsg<JSONObject>();
			LOGGER.error("查询活动中的活动列表异常", e);
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0042);
			returnMsg.setErrorMessage(String.format(returnMsg.getErrorMessage(), e.getMessage()));
			return returnMsg;
		}
	}

	@Override
	public ReturnMsg<CustomerVo> queryCustomerByPhone(String mobileMW, String source, String activityId, String staffId) {
		ReturnMsg<CustomerVo> returnMsg = new ReturnMsg<CustomerVo>();
		if (checkNull(mobileMW, source)) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0044);
			returnMsg.setErrorMessage(String.format(returnMsg.getErrorMessage(), "手机号和来源不可以为空"));
			return returnMsg;
		}
		// 如果是门店外拓，必须要传活动id
		if (String.valueOf(MemberConstants.STORE_EXPEND).equals(source)) {
			if (checkNull(activityId)) {
				returnMsg.setError(ErrorCodeConstants.ERR_MEM_0044);
				returnMsg.setErrorMessage(String.format(returnMsg.getErrorMessage(), "门店外拓时，活动id不可以为空"));
				return returnMsg;
			}
		}

		try {
			// 解密手机号
			mobileMW = mobileMW.replace(" ", "+");
			String mobile = AESUtils.decrypt(mobileMW, ConfigConstants.AES_KEY);
			if (mobile == null) {
				returnMsg.setError(ErrorCodeConstants.ERR_MEM_0044);
				returnMsg.setErrorMessage(String.format(returnMsg.getErrorMessage(), "手机解密失败"));
				return returnMsg;
			}
			StoreManDto storeMan = storeManService.queryStoreManAttachInfo(staffId);

			// 查询客户基本信息
			CustomerVo customer = activityDao.findCustomerByPhone(mobile, staffId);

			if (customer == null) {// 新客户
				customer = new CustomerVo();
				setCustInfo(mobile, customer);
			} else {
				// 该客户已经参加此活动了
				if (StringUtils.isNotEmpty(activityId) && activityDao.checkCustomerJoinActivity(mobile, storeMan.getStoreCode(), Long.parseLong(activityId))) {
					returnMsg.setError(ErrorCodeConstants.ERR_MEM_0043);
					return returnMsg;
				}
				// 是老客户，但是当初不是会员,再去查一下
				if (StringUtils.isEmpty(customer.getCustNum()) || StringUtils.isEmpty(customer.getLevel())) {
					setCustInfo(mobile, customer);
				}
				// 根据手机号，来源，店员，查询之前有无拓展过此客户
				CustomerVo detail = activityDao.findCustomerDetailByPhoneSourceEmployeeId(mobile, source, staffId);
				if (detail != null) {
					customer.setCustDetailId(detail.getCustDetailId());
					customer.setActivityId(detail.getActivityId());
					customer.setActivityName(detail.getActivityName());
				}

				// 查询意向品类
				List<Map<String, Object>> cates = activityDao.queryIntentCateByCustDetailId(customer.getCustDetailId());
				// 查询意向商品
				List<Map<String, Object>> cmmdties = activityDao.queryIntentCmmdtyByCustDetailId(customer.getCustDetailId());
				// 查询标签信息
				List<CustLabelVo> custLabels = labelDao.selectLabelByCust(customer.getCustId());

				customer.setCustLabels(custLabels);
				customer.setCates(cates);
				customer.setCmmdties(cmmdties);
			}
			customer.setMobile(mobileMW);
			returnMsg.setData(customer);
		} catch (Exception e) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0044);
			returnMsg.setErrorMessage(String.format(returnMsg.getErrorMessage(), e.getMessage()));
			LOGGER.error("根据手机号查询会员信息异常", e);
		}

		return returnMsg;
	}

	/**
	 * 
	 * 根据手机号查询会员相关信息，如果找到了，则赋值给vo
	 *
	 * @param mobile
	 * @param customer
	 */
	private void setCustInfo(String mobile, CustomerVo customer) {
		LocateMemberInfo memberInfo = memberInfoService.locateMemberByMobileNo(mobile);
		String custNo = memberInfo.getCustNum();
		if (memberInfo != null && StringUtils.isNotBlank(custNo)) {
			customer.setCustNum(custNo);
			CustSocietyInfoStruct infoStruct = queryMemberInfoByCustNo(custNo);
			if (infoStruct != null) {
				// 客户等级
				String level = MemberConstants.CUST_LEVEL.get(infoStruct.getCustLevelNum());
				customer.setLevel(level);
			}
		}
	}

	private CustSocietyInfoStruct queryMemberInfoByCustNo(String custNo) {
		List<String> custNumList = new ArrayList<String>();
		custNumList.add(custNo);
		QuerySocialityInfoResp infoResp = memberInfoService.querySocialityInfoAConstellation(custNumList);
		if (null != infoResp && null != infoResp.getBody()) {
			if (CollectionUtils.isNotEmpty(infoResp.getBody().getCustSocietyInfoStructList())) {
				CustSocietyInfoStruct infoStruct = infoResp.getBody().getCustSocietyInfoStructList().get(0);
				return infoStruct;
			}
		}
		LOGGER.warn("根据custNo查询促销会员信息为空;custNo：{},返回的对象为：{}", custNo, infoResp);
		return null;
	}

	// 新增编辑会员
	@Override
	@Transactional
	public ReturnMsg<MemCustomerDetailResponse> saveOrUpdateCustomer(MemCustomerDetailResponse customerDetailVo, String staffId) {
		ReturnMsg<MemCustomerDetailResponse> returnMsg = new ReturnMsg<MemCustomerDetailResponse>();
		StoreManDto storeMan = null;
		try {
			// 根据当前登录人的工号，查询此人相关的一系列信息
			storeMan = storeManService.queryStoreManAttachInfo(staffId);
			checkMember(returnMsg, customerDetailVo, storeMan);
			if (ReturnMsg.FAIL.equals(returnMsg.getRetFlag())) {
				return returnMsg;
			}
		} catch (Exception e) { // 判断各种校验，发生异常，则告诉给前端
			LOGGER.error("保护客户资料异常", e);
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0046);
			returnMsg.setErrorMessage(String.format("保存失败:%s", e.getMessage()));
			return returnMsg;
		}

		int isUpdate = customerDetailVo.getIsUpdate();

		if (isUpdate == MemberConstants.ONE.intValue()) { // 更新
			updateCustomer(returnMsg, customerDetailVo, storeMan);
		} else {// 新增
			saveCustomer(returnMsg, customerDetailVo, storeMan);
			// 新增了一个客户了，统计数据会发生变化，缓存需要更新，故删除缓存
			String activityListKeys = String.format(CacheKeyConstants.MemberExpand.ACTIVITY_LIST, storeMan.getStoreCode(), 0);
			redisClient.del(activityListKeys);
		}
		Long custId = customerDetailVo.getCustId();
		// 删除老的标签信息
		labelDao.delMemLabelRelByCustId(custId);
		// 设置新标签信息
		this.saveMemLabelRel(customerDetailVo.getLabelIds(), staffId, custId);
		return returnMsg;
	}

	// 更新会员
	public ReturnMsg<MemCustomerDetailResponse> updateCustomer(ReturnMsg<MemCustomerDetailResponse> returnMsg, MemCustomerDetailResponse customerDetailVo, StoreManDto storeMan) {
		LOGGER.info("更新客户资料vo:{}", customerDetailVo);

		try {
			// 2、同步更新 mem_customer，mem_customer_detail
			CustomerDetail customerDetail = getCustomerDetailFromVo(customerDetailVo, storeMan, true);
			customerDao.updateMemCustomerDetail(customerDetail);
			Long detailId = customerDetail.getId();
			MemCustomer customer = getCustomerFromVo(customerDetailVo, storeMan, detailId, true);
			customerDao.updateMemCustomer(customer);

			// 更新之前，删除老数据
			customerDao.deleteIntentCateByDetailId(detailId);
			List<MemCustomerIntentCate> cates = getCates(customerDetailVo, detailId);
			if (!CollectionUtils.isEmpty(cates)) {
				customerDao.batchSaveMemCustomerIntentCate(cates);
			}
			// 更新前，删除老数据
			customerDao.deleteIntentCmmdtyByDetailId(detailId);
			List<MemCustomerIntentCmmdty> cmmdties = getCmmdties(customerDetailVo, detailId);
			if (!CollectionUtils.isEmpty(cmmdties)) {
				customerDao.batchSaveMemCustomerIntentCmmdty(cmmdties);
			}
		} catch (Exception e) {
			LOGGER.error("保存客户资料异常", e);
			throw new SawpException("保存客户资料异常", e);
		}
		return returnMsg;
	}

	// 新增会员
	public ReturnMsg<MemCustomerDetailResponse> saveCustomer(ReturnMsg<MemCustomerDetailResponse> returnMsg, MemCustomerDetailResponse customerDetailVo, StoreManDto storeMan) {
		LOGGER.info("保存客户资料vo:{}", customerDetailVo);

		try {
			Long activityId = customerDetailVo.getActivityId();
			String mobile = customerDetailVo.getMobile();
			// 该客户已经参加此活动了
			if (activityId != null && activityDao.checkCustomerJoinActivity(mobile, storeMan.getStoreCode(), activityId)) {
				returnMsg.setError(ErrorCodeConstants.ERR_MEM_0043);
				return returnMsg;
			}
			// 判断任务的时间范围
			if (String.valueOf(MemberConstants.STORE_EXPEND).equals(customerDetailVo.getSource())) {
				StoreExpandVo storeExpand = activityDao.findExpandById(customerDetailVo.getExpandId());
				Date startTime = DateTime.parse(storeExpand.getStartTime(), MemberConstants.formatter).toDate();
				Date endTime = DateTime.parse(storeExpand.getEndTime(), MemberConstants.formatter).toDate();
				// 结束日期加1，方便判断最后一天范围
				endTime = DateUtils.getNextDay(endTime, 1);
				Date now = new Date();
				// 不在任务时间范围内
				if (!(now.after(startTime) && now.before(endTime))) {
					returnMsg.setError(ErrorCodeConstants.ERR_MEM_0047);
					return returnMsg;
				}
			}

			// 2、同步入库 mem_customer，mem_customer_detail
			CustomerDetail customerDetail = getCustomerDetailFromVo(customerDetailVo, storeMan, false);
			customerDao.saveMemCustomerDetail(customerDetail);
			Long detailId = customerDetail.getId();
			MemCustomer customer = getCustomerFromVo(customerDetailVo, storeMan, detailId, false);
			if (customerDetailVo.getCustId() == null) {
				customerDao.saveMemCustomer(customer);
				// 回塞一下，是为了接下来会员标签的逻辑
				customerDetailVo.setCustId(customer.getId());
			} else {// 之前存在过的老客户，又被拓展了，此时是需要新增到详情表，更新基础表
				customer.setId(customerDetailVo.getCustId());
				customerDao.updateMemCustomer(customer);
			}
			List<MemCustomerIntentCate> cates = getCates(customerDetailVo, detailId);
			if (!CollectionUtils.isEmpty(cates)) {
				customerDao.batchSaveMemCustomerIntentCate(cates);
			}
			List<MemCustomerIntentCmmdty> cmmdties = getCmmdties(customerDetailVo, detailId);
			if (!CollectionUtils.isEmpty(cmmdties)) {
				customerDao.batchSaveMemCustomerIntentCmmdty(cmmdties);
			}
		} catch (Exception e) {
			LOGGER.error("保存客户资料异常", e);
			throw new SawpException("保存客户资料异常", e);
		}
		return returnMsg;
	}

	/**
	 * 
	 * 保存的时候，检查会员资料是否提交完整
	 */
	private void checkMember(ReturnMsg<MemCustomerDetailResponse> returnMsg, MemCustomerDetailResponse customerDetail, StoreManDto storeMan) {
		String mobileMW = customerDetail.getMobile();
		String custName = customerDetail.getCustName();
		String source = customerDetail.getSource();
		Long expandId = customerDetail.getExpandId();
		Long activityId = customerDetail.getActivityId();

		String custNo = customerDetail.getCustNo();
		String level = customerDetail.getLevel();

		String errorMsg = StringUtils.EMPTY;
		returnMsg.setError(ErrorCodeConstants.ERR_MEM_0045);

		mobileMW = mobileMW.replace(" ", "+");
		String mobile = AESUtils.decrypt(mobileMW, ConfigConstants.AES_KEY);
		if (mobile == null) {
			errorMsg = "手机号解密出错";
			returnMsg.setErrorMessage(errorMsg);
			return;
		}
		customerDetail.setMobile(mobile);
		// 更新
		if (customerDetail.getIsUpdate() == MemberConstants.ONE.intValue()) {
			// 更新的时候，貌似没啥特殊校验
		} else {
			if (checkNull(mobileMW, custName, source)) {
				errorMsg = "参数不可以为空";
				returnMsg.setErrorMessage(errorMsg);
				return;
			}
			// 门店外拓
			if (String.valueOf(MemberConstants.STORE_EXPEND).equals(source)) {
				// 门店外拓的时候，活动id和外拓任务id，必须要传
				if (activityId == null || expandId == null) {
					errorMsg = "参数不可以为空(活动id,外拓任务id)";
					returnMsg.setErrorMessage(errorMsg);
					return;
				}
			} else if (String.valueOf(MemberConstants.INQUIRY_NOT_BUY).equals(source)) { // 询价未购的时候，判断当前登录人的品类
				List<Category> categories = storeMan.getCategories();
				if (CollectionUtils.isEmpty(categories)) {
					errorMsg = "登录人员暂无品类信息，请联系hr维护";
					returnMsg.setErrorMessage(errorMsg);
					return;
				}
			}
		}
		if (Integer.parseInt(source) < 3) { // 门店外拓，询价未购的时候，金额必传
			if (customerDetail.getExpectPay() == null || !checkNumber(customerDetail.getExpectPay())) {
				errorMsg = "预估金额格式不正确";
				returnMsg.setErrorMessage(errorMsg);
				return;
			}
		}

		// 品牌名称不可以超过20
		if (CollectionUtils.isNotEmpty(customerDetail.getCates())) {
			for (MemCustomerIntentCateVo ic : customerDetail.getCates()) {
				String brands = ic.getBrands();
				if (brands != null && brands.length() > 20) {
					errorMsg = "品牌名称长度不可以超过20个字符";
					returnMsg.setErrorMessage(errorMsg);
					return;
				}
			}
		}

		if (customerDetail.getCommoditys() != null && customerDetail.getCommoditys().size() > 10) {
			errorMsg = "意向商品不可以超过10个";
			returnMsg.setErrorMessage(errorMsg);
			return;
		}

		// 注册的时候，如果只有会员，没有level的时候，则查询下level
		if (StringUtils.isNotEmpty(custNo) && StringUtils.isEmpty(level)) {
			CustSocietyInfoStruct info = queryMemberInfoByCustNo(custNo);
			if (info != null) {
				String levelNewest = MemberConstants.CUST_LEVEL.get(info.getCustLevelNum());
				customerDetail.setLevel(levelNewest);
			}
		}

		// 没有错误，改回成功
		if (StringUtils.isEmpty(errorMsg)) {
			returnMsg.setRetFlag(ReturnMsg.SUCCESS);
			returnMsg.setErrorCode(StringUtils.EMPTY);
			returnMsg.setErrorMessage(errorMsg);
		}
	}

	/**
	 * 
	 * 获取会员基础信息
	 *
	 * @param customerDetailVo
	 * @param storeMan
	 */
	private MemCustomer getCustomerFromVo(MemCustomerDetailResponse customerDetailVo, StoreManDto storeMan, Long detailId, boolean isUpdate) {
		MemCustomer customer = new MemCustomer();

		customer.setName(customerDetailVo.getCustName());
		customer.setEmployeeId(storeMan.getStaffId());
		customer.setEmployeeName(storeMan.getStaffName());
		if (customerDetailVo.getExpectDate() != null) {
			customer.setExpectDate(DateTime.parse(customerDetailVo.getExpectDate(), MemberConstants.formatter).toDate());
		}
		if (customerDetailVo.getExpectPay() != null) {
			customer.setExpectPay(new BigDecimal(customerDetailVo.getExpectPay()));
		}
		customer.setCustNo(customerDetailVo.getCustNo());
		customer.setLevel(customerDetailVo.getLevel());
		customer.setMemberDetailId(detailId);
		if (isUpdate) { // 更新的时候，只会修改部分属性
			customer.setId(customerDetailVo.getCustId());
			customer.setUpdateTime(new Date());
			return customer;
		}

		customer.setMobile(customerDetailVo.getMobile());
		customer.setCreateTime(new Date());
		customer.setStoreCode(storeMan.getStoreCode());
		customer.setShared(MemberConstants.ZERO);

		return customer;
	}

	/**
	 * 
	 * 获取会员详情
	 *
	 * @param customerDetailVo
	 * @param storeMan
	 * @return
	 */
	private CustomerDetail getCustomerDetailFromVo(MemCustomerDetailResponse customerDetailVo, StoreManDto storeMan, boolean isUpdate) {
		CustomerDetail detail = new CustomerDetail();

		detail.setName(customerDetailVo.getCustName());
		detail.setEmployeeId(storeMan.getStaffId());
		detail.setEmployeeName(storeMan.getStaffName());

		if (customerDetailVo.getExpectDate() != null) {
			detail.setExpectDate(DateTime.parse(customerDetailVo.getExpectDate(), MemberConstants.formatter).toDate());
		}
		if (customerDetailVo.getExpectPay() != null) {
			detail.setExpectPay(new BigDecimal(customerDetailVo.getExpectPay()));
		}
		detail.setCustNo(customerDetailVo.getCustNo());
		detail.setLevel(customerDetailVo.getLevel());

		List<MemCustomerIntentCateVo> cates = customerDetailVo.getCates();
		List<MemCustomerIntentCmmdtyVo> commoditys = customerDetailVo.getCommoditys();
		int cateLength = (cates == null) ? 0 : cates.size();
		int cmmdtyLength = (commoditys == null) ? 0 : commoditys.size();

		if (isUpdate) { // 更新的时候，只会修改部分属性
			if (cateLength + cmmdtyLength == 1) {
				detail.setBuyType(MemberConstants.ONE);
			} else if (cateLength + cmmdtyLength > 1) {
				detail.setBuyType(MemberConstants.TWO);
			}// 如果等于0，维持新增时候的状态
			detail.setId(customerDetailVo.getDetailId());
			return detail;
		}

		if (cateLength + cmmdtyLength > 1) { // 套购
			detail.setBuyType(MemberConstants.TWO);
		} else { // 单品
			detail.setBuyType(MemberConstants.ONE);
		}

		detail.setMobile(customerDetailVo.getMobile());
		detail.setCreateTime(new Date());
		detail.setActivityId(customerDetailVo.getActivityId());
		detail.setActivityName(customerDetailVo.getActivityName());
		detail.setSource(Short.parseShort(customerDetailVo.getSource()));
		if (detail.getSource().intValue() < 3) { // 门店外拓，询价未购，需要传mode
			detail.setMode(Short.parseShort(customerDetailVo.getMode()));
		}
		detail.setStoreCode(storeMan.getStoreCode());
		Long expandId = customerDetailVo.getExpandId();
		if (expandId != null) {
			detail.setExpandId(expandId);
			StoreExpandVo storeExpand = activityDao.findExpandById(expandId);
			detail.setCateCode(storeExpand.getCateCode());
		} else {
			List<Category> categories = storeMan.getCategories();
			if (CollectionUtils.isNotEmpty(categories)) {
				// 询价未购的时候，以店员自身的品类为主
				detail.setCateCode(categories.get(0).getCategoryCode());
			}
		}
		detail.setMemo(customerDetailVo.getMemo());

		return detail;
	}

	/**
	 * 
	 * 获取意向品类列表
	 *
	 * @param customerDetailVo
	 * @param detailId
	 * @return
	 */
	private List<MemCustomerIntentCate> getCates(MemCustomerDetailResponse customerDetailVo, Long detailId) {
		List<MemCustomerIntentCateVo> cates = customerDetailVo.getCates();
		if (CollectionUtils.isEmpty(cates)) {
			return null;
		}
		List<MemCustomerIntentCate> resultList = new ArrayList<MemCustomerIntentCate>();
		for (MemCustomerIntentCateVo cate : cates) {
			MemCustomerIntentCate intentCate = new MemCustomerIntentCate();
			intentCate.setCateCode(cate.getCateCode());
			intentCate.setCateName(cate.getCateName());
			intentCate.setBrands(cate.getBrands());
			intentCate.setCustomerDetailId(detailId);
			resultList.add(intentCate);
		}
		return resultList;
	}

	/**
	 * 
	 * 获取意向商品列表
	 *
	 * @param customerDetailVo
	 * @param detailId
	 * @return
	 */
	private List<MemCustomerIntentCmmdty> getCmmdties(MemCustomerDetailResponse customerDetailVo, Long detailId) {
		List<MemCustomerIntentCmmdtyVo> cmmdties = customerDetailVo.getCommoditys();
		if (CollectionUtils.isEmpty(cmmdties)) {
			return null;
		}
		List<MemCustomerIntentCmmdty> resultList = new ArrayList<MemCustomerIntentCmmdty>();
		for (MemCustomerIntentCmmdtyVo cmmdty : cmmdties) {
			MemCustomerIntentCmmdty intentCmmdty = new MemCustomerIntentCmmdty();
			intentCmmdty.setCmmdtyCode(cmmdty.getCmmdtyCode());
			intentCmmdty.setCmmdtyName(cmmdty.getCmmdtyName());
			intentCmmdty.setCustomerDetailId(detailId);
			resultList.add(intentCmmdty);
		}
		return resultList;
	}

	@Override
	public ReturnMsg<JSONObject> queryPlaceList4Emp(Long activityId, String staffId, int startIndex) {
		LOGGER.info("店员{}查询外拓任务地点列表，活动id:{}", staffId, activityId);
		ReturnMsg<JSONObject> returnMsg = new ReturnMsg<JSONObject>();
		JSONObject json = new JSONObject();
		if (activityId == null) {
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0048);
			returnMsg.setErrorMessage("活动id不可为空");
			return returnMsg;
		}

		try {
			StoreManDto storeMan = storeManService.queryStoreManAttachInfo(staffId);
			String storeCode = storeMan.getStoreCode();

			// 非店员不可访问
			if (!(ClerkConstants.SALES_CLERK.equals(storeMan.getPositionId()) || ClerkConstants.SALES_PROMOTION.equals(storeMan.getPositionId()))) {
				LOGGER.warn("只有店员才可访问，当前操作人：{}({})，非店员角色.", storeMan.getStaffName(), storeMan.getStaffId());
				returnMsg.setError(ErrorCodeConstants.ERR_MEM_0048);
				returnMsg.setErrorMessage("对不起，你不是店员呢");
				return returnMsg;
			}

			if (startIndex == 0) {
				MemberExtensionStatisVo activityStatistic4Emp = activityDao.findPlaceStatistics4Emp(activityId, storeCode, staffId);
				json.put("statistic", activityStatistic4Emp);
			}
			// 查询分配的地点总数
			Long total = activityDao.countPlaceList4Emp(activityId, storeMan.getStoreCode(), staffId);
			json.put("total", total);

			List<StoreExpandVo> expandList = null;

			// 如果统计的数量大于0，则分页获取数据
			if (total > 0) {
				expandList = activityDao.queryPlaceList4Emp(activityId, storeCode, staffId, startIndex, MemberConstants.PAGE_SIZE);
			}
			// 没数据，或者未查询到的情况下，返回空对象
			if (CollectionUtils.isEmpty(expandList)) {
				expandList = new ArrayList<StoreExpandVo>(0);
			}
			json.put("expandList", expandList);
			returnMsg.setData(json);
		} catch (Exception e) {
			LOGGER.error("店员:{}查询参与的活动：{} 地点列表异常", staffId, activityId, e);
			returnMsg.setError(ErrorCodeConstants.ERR_MEM_0048);
			String errorMsg = String.format(returnMsg.getErrorMessage(), e.getMessage());
			returnMsg.setErrorMessage(errorMsg);
		}

		return returnMsg;
	}

	/**
	 * 
	 * 查询某门店当月创建活动的数量
	 *
	 * @param storeCode
	 * @return
	 */
	@Override
	public Long countStoreActivity(String storeCode) {
		// 获取当月1号，和下月1号
		String startTime = DateUtils.getDateStrByFormat(DateUtils.getFirstDayZeroPointOfMonth(0), DateUtils.DEFAULT_DAY_PATTERN);
		String endTime = DateUtils.getDateStrByFormat(DateUtils.getFirstDayZeroPointOfMonth(1), DateUtils.DEFAULT_DAY_PATTERN);
		Long num = activityDao.countActivityNumPerMonth(storeCode, startTime, endTime);
		if (num != null) {
			return num;
		}
		return 0L;
	}

	/**
	 * 对活动有增删改查等情况需要清除缓存
	 */
	private void delActivityKey(String storeCode) {
		// 活动列表
		String activityListKeys = String.format(CacheKeyConstants.MemberExpand.ACTIVITY_LIST, storeCode, 0);
		// 进行中的活动列表
		String activeActivityListKey = String.format(CacheKeyConstants.MemberExpand.ACTIVITY_ACTIVE_LIST, storeCode);

		redisClient.del(activityListKeys);
		redisClient.del(activeActivityListKey);

	}

	/**
	 * 活动结束一个月后，处理mem_sale表里面过期的数据
	 */
	@Override
	public void preocessExpiredActivity() {
		// 处理结束超过一个月的活动数据
		String endTime = DateUtils.getNextMonthStr(new Date(), DateUtils.DEFAULT_DAY_PATTERN, -1);
		List<Activity> activityList = activityDao.queryActivityListByEndTime(endTime);
		if (CollectionUtils.isNotEmpty(activityList)) {
			for (Activity activity : activityList) {
				activityDao.delSaleByActivityId(activity.getId());
			}
		}
	}

	public void processCustomerNo() {
		LOGGER.info("定时查询非会员客户");
		// 非会员的客户
		try {
			// 查询所有非会员客户
			List<CustomerVo> custList = activityDao.queryNoMemberCust();
			LOGGER.info("查询到的客户列表为：{}", custList);
			List<CustomerDetail> detailList = new ArrayList<CustomerDetail>();
			List<MemCustomer> customerList = new ArrayList<MemCustomer>();
			for (CustomerVo cust : custList) {
				setCustInfo(cust.getMobile(), cust);
				// 发现是会员了。那么就记录下，留待后面批量更新
				if (StringUtils.isNotEmpty(cust.getCustNum())) {
					CustomerDetail detail = new CustomerDetail();
					detail.setId(Long.parseLong(cust.getCustDetailId()));
					detail.setCustNo(cust.getCustNum());
					detail.setLevel(cust.getLevel());
					detailList.add(detail);

					// 更新memCustomer的custNo
					MemCustomer memCustomer = new MemCustomer();
					memCustomer.setMobile(cust.getMobile());
					memCustomer.setCustNo(cust.getCustNum());
					memCustomer.setLevel(cust.getLevel());
					customerList.add(memCustomer);
				}
				Thread.sleep(900L);// 每秒调用一次，防止太频繁，拖垮了对方系统
			}
			LOGGER.info("查询到的会员对象为：{}", detailList);
			customerDao.batchUpdateCustomerDetail(detailList);
			customerDao.batchUpdateCustomer(customerList);
		} catch (Exception e) {
			LOGGER.error("处理非会员数据发生异常", e);
		}
	}

	/**
	 * 
	 * 处理老会员
	 *
	 */
	@Transactional
	public void processOldCust(String createTime) {
		LOGGER.info("开始处理老会员转到新表中...");
		activityDao.moveOldCust2New(createTime);
		activityDao.moveDetailToList(createTime);
		LOGGER.info("已结束：老会员已转到新表中！");
	}

	public CustomerDetail queryCustomerDetailByParams(String custNo, String employeeId, String source) {
		return activityDao.queryCustomerDetailByParams(custNo, employeeId, source);
	}

	public MemCustomer queryCustomerByParams(String custNo, String employeeId) {
		return activityDao.queryCustomerByParams(custNo, employeeId);
	}

	public void saveMemLabelRel(String ids, String empolyeeId, Long custId) {
		if (StringUtils.isEmpty(ids)) {
			return;
		}
		// 会员与标签的关系列表
		List<MemLabelRel> memLabelRels = new ArrayList<MemLabelRel>();
		String idArray[] = ids.split(",");
		Map<String, Object> params = new HashMap<String, Object>();
		for (String labelId : idArray) {
			params.put("labelId", labelId);
			LabelVo labelVo = labelDao.selectLabelInfo(params);
			if (labelVo == null) {// 没查到就忽略
				continue;
			}
			MemLabelRel memLabelRel = new MemLabelRel();
			memLabelRel.setCustId(custId);
			memLabelRel.setCreateUser(empolyeeId);
			memLabelRel.setLabelId(Long.parseLong(labelId));
			memLabelRel.setLabelName(labelVo.getLabelName());
			memLabelRels.add(memLabelRel);
			params.clear();
		}
		// 批量保存
		labelDao.batchSaveMemLabelRel(memLabelRels);
	}
}
